﻿#Region "Copyright"
'————————————————————————————————————————
'	创建人员(Creator)    ：Huangyd
'	创建日期(Date)       ：2012-07-14
'   联系方式(Email)      ：aj-ayumi@163.com; gajayumi@gmail.com; ajayumi@me.com
'   描    述(Description)：
'
'	Copyright (C) 2012 ajayumi 版权所有
'————————————————————————————————————————
#End Region
Imports System.Drawing
Imports System.Runtime.InteropServices
Imports System.Drawing.Drawing2D
Imports System.Drawing.Imaging
Imports System.IO
Imports ajayumi.develop.VBasic.Core.Drawing.Watermark

Namespace Drawing

    ''' <summary>
    ''' ImageHelper 图片处理类
    ''' Author  ajayumi
    ''' Date    2010-01-14
    ''' </summary>
    ''' <remarks></remarks>
    Public Class ImageHelper
        Implements IDisposable

        Private disposed As Boolean = False        ' To detect redundant calls

        ' IDisposable
        Protected Overridable Sub Dispose(ByVal disposing As Boolean)
            If Not Me.disposed Then
                If disposing Then
                    ' Free other state (managed objects).
                End If
                ' Free your own state (unmanaged objects).
                ' Set large fields to null.
            End If
            Me.disposed = True
        End Sub

#Region " IDisposable Support "
        ' This code added by Visual Basic to correctly implement the disposable pattern.
        Public Sub Dispose() Implements IDisposable.Dispose
            ' Do not change this code.  Put cleanup code in Dispose(ByVal disposing As Boolean) above.
            Dispose(True)
            GC.SuppressFinalize(Me)
        End Sub

        Protected Overrides Sub Finalize()
            ' Do not change this code.  Put cleanup code in Dispose(ByVal disposing As Boolean) above.
            Dispose(False)
            MyBase.Finalize()
        End Sub
#End Region


#Region "shared"



        ''' <summary>
        ''' 根据文件后缀名判断是否为图片文件
        ''' </summary>
        ''' <param name="fileName">文件名</param>
        ''' <returns>是图片则返回布尔真值</returns>
        Public Shared Function IsImageFile(ByVal fileName As String) As Boolean
            Return System.Text.RegularExpressions.Regex.Match(fileName, _
                                                              "[^/\*\\?<>\|]+(\.jpg|\.gif|\.bmp|\.png)$", System.Text.RegularExpressions.RegexOptions.IgnoreCase).Success
        End Function



        ''' <summary>
        ''' 图片转字符串
        ''' </summary>
        ''' <param name="imgPath">图片路径</param>
        ''' <param name="format">图片格式</param>
        ''' <returns></returns>
        Public Shared Function ImageToBase64String(ByVal imgPath As String, ByVal format As ImageFormat) As String
            Dim _Result As String = String.Empty
            If IsImageFile(imgPath) = True Then
                Dim _Image As Image = Image.FromFile(imgPath)
                Using ms As New MemoryStream
                    _Image.Save(ms, format)
                    _Result = System.Convert.ToBase64String(ms.GetBuffer())
                End Using
            End If
            Return _Result
        End Function
        ''' <summary>
        ''' 图片转字符串
        ''' </summary>
        ''' <param name="img"></param>
        ''' <param name="format"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared Function ImageToBase64String(ByVal img As Image, ByVal format As ImageFormat) As String
            Dim _Result As String = String.Empty

            Using ms As New MemoryStream()
                img.Save(ms, format)
                _Result = System.Convert.ToBase64String(ms.GetBuffer())
            End Using

            Return _Result
        End Function

        ''' <summary>
        ''' 字符串转图片
        ''' </summary>
        ''' <param name="base64String">字符串</param>
        ''' <returns></returns>
        Public Shared Function Base64StringToImage(ByVal base64String As String) As Image
            Dim _Bytes() As Byte = CType(Convert.FromBase64String(base64String), Byte())
            Dim _Image As Image = Nothing

            Using ms As New MemoryStream(_Bytes)
                _Image = Image.FromStream(ms)
            End Using

            Return _Image
        End Function

        Public Shared Function imageToByteArray(ByVal img As Image, ByVal format As ImageFormat) As Byte()
            Dim ms As New MemoryStream()
            img.Save(ms, format)
            Return ms.ToArray()
        End Function 'imageToByteArray


        Public Shared Function byteArrayToImage(ByVal byteArrayIn() As Byte) As Image
            Dim _Image As Image = Nothing
            Using ms As New MemoryStream(byteArrayIn)
                _Image = Image.FromStream(ms)
            End Using
            Return _Image
        End Function 'byteArrayToImage 


        ''' <summary>
        ''' 根据指定的 Rectangle 裁切图片
        ''' </summary>
        ''' <param name="img">待裁切图片</param>
        ''' <param name="cropArea">裁切区域</param>
        ''' <returns>Image</returns>
        Private Shared Function CropImage(ByVal img As Image, ByVal cropArea As Rectangle) As Image
            Try
                Dim _Bitmap As New Bitmap(img)
                Dim _CropBitmap As Bitmap = _Bitmap.Clone(cropArea, _Bitmap.PixelFormat)
                Return DirectCast((_CropBitmap), Image)
            Catch ex As Exception
                Throw ex
            End Try

            Return Nothing
        End Function


        ''' <summary> 
        ''' 获取图像编码解码器的所有相关信息 
        ''' </summary> 
        ''' <param name="mimeType">包含编码解码器的多用途网际邮件扩充协议 (MIME) 类型的字符串,如：image/jpeg</param> 
        ''' <returns>返回图像编码解码器的所有相关信息</returns> 
        Public Shared Function GetImageCodecInfo(ByVal mimeType As String) As ImageCodecInfo
            Dim CodecInfo As ImageCodecInfo() = ImageCodecInfo.GetImageEncoders()
            For Each ici As ImageCodecInfo In CodecInfo
                If ici.MimeType = mimeType Then
                    Return ici
                End If
            Next

            Return Nothing
        End Function

        ''' <summary>
        ''' 获取图像编码解码器的所有相关信息 
        ''' </summary>
        ''' <param name="format">图片格式</param>
        ''' <returns>返回图像编码解码器的所有相关信息</returns>
        Public Shared Function GetImageCodecInfo(ByVal format As ImageFormat) As ImageCodecInfo
            Dim encoders As ImageCodecInfo() = ImageCodecInfo.GetImageEncoders()

            For Each icf As ImageCodecInfo In encoders
                If icf.FormatID = format.Guid Then
                    Return icf
                End If
            Next

            Return Nothing
        End Function

        ''' <summary>
        ''' 保存图片
        ''' </summary>
        ''' <param name="img"></param>
        ''' <param name="savePath"></param>
        ''' <remarks></remarks>
        Public Shared Sub SaveImage(ByVal img As Image, ByVal savePath As String)
            SaveImage(img, savePath, GetImageCodecInfo(Imaging.ImageFormat.Jpeg))
        End Sub

        ''' <summary> 
        ''' 高质量保存图片 
        ''' </summary> 
        ''' <param name="img"></param> 
        ''' <param name="savePath"></param> 
        ''' <param name="ici"></param> 
        Public Shared Sub SaveImage(ByVal img As Image, ByVal savePath As String, ByVal ici As ImageCodecInfo)
            SaveImage(img, savePath, ici, 80L)
        End Sub

        ''' <summary>
        ''' 高质量保存图片 
        ''' </summary>
        ''' <param name="img"></param>
        ''' <param name="savePath"></param>
        ''' <param name="ici"></param>
        ''' <param name="quality"></param>
        ''' <remarks></remarks>
        Public Shared Sub SaveImage(ByVal img As Image, ByVal savePath As String, ByVal ici As ImageCodecInfo, ByVal quality As Long)
            ' 设置 原图片 对象的 EncoderParameters 对象 
            Dim _EncoderParams As New EncoderParameters(1)
            Dim _QualityParam As New EncoderParameter(System.Drawing.Imaging.Encoder.Quality, CLng(quality))
            _EncoderParams.Param(0) = _QualityParam

            Dim _Directory As String = Path.GetDirectoryName(savePath)
            If Not Directory.Exists(_Directory) Then
                Directory.CreateDirectory(_Directory)
            End If
            img.Save(savePath, ici, _EncoderParams)

            _QualityParam.Dispose()
            _EncoderParams.Dispose()
        End Sub
#End Region



#Region "私有方法"

        ''' <summary>
        ''' 得到矩形中心
        ''' </summary>
        ''' <param name="width">指定的宽度</param>
        ''' <param name="height">指定的高度</param>
        ''' <param name="thumbnailSize">缩略图的尺寸</param>
        ''' <returns></returns>
        Private Function getCenterRectangle(ByVal width As Integer, ByVal height As Integer, ByVal thumbnailSize As Size) As Rectangle
            Dim _Width As Integer = width
            Dim _Height As Integer = height

            If width > thumbnailSize.Width Then
                _Width = thumbnailSize.Width
                _Height = CInt(thumbnailSize.Width * height / width)
            End If

            If height > thumbnailSize.Height Then
                _Width = CInt(thumbnailSize.Height * width / height)
                _Height = thumbnailSize.Height
            End If

            Dim _Rectangle As Rectangle = New Rectangle( _
                                                        CInt((thumbnailSize.Width - _Width) / 2), _
                                                        CInt((thumbnailSize.Height - _Height) / 2), _
                                                        _Width, _Height)

            Return _Rectangle
        End Function


#End Region

#Region "公有方法"

        ''' <summary> 
        ''' Creates an Image with a Glass Table effect 
        ''' </summary> 
        ''' <param name="img">Original image</param> 
        ''' <param name="bgColor">New image background color</param> 
        ''' <param name="reflectivity">Reflectivity (0 to 255)</param> 
        ''' <remarks>Image newImage = ImageEffectsHelper.DrawReflection(pOriginal.Image, Color.White, 90);</remarks>
        Public Function DrawReflection(ByVal img As Image, ByVal bgColor As Color, ByVal reflectivity As Integer) As Image
            ' Calculate the size of the new image 
            Dim height As Integer = CInt((img.Height + (img.Height * (CSng(reflectivity) / 255))))
            Dim newImage As New Bitmap(img.Width, height, PixelFormat.Format24bppRgb)
            newImage.SetResolution(img.HorizontalResolution, img.VerticalResolution)

            Using _Graphics As Graphics = Graphics.FromImage(newImage)
                ' Initialize main graphics buffer 
                _Graphics.Clear(bgColor)
                _Graphics.DrawImage(img, New Point(0, 0))
                _Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic
                Dim destinationRectangle As New Rectangle(0, img.Size.Height, img.Size.Width, img.Size.Height)

                ' Prepare the reflected image 
                Dim reflectionHeight As Integer = CInt((img.Height * reflectivity) / 255)
                Dim reflectedImage As Image = New Bitmap(img.Width, reflectionHeight)

                ' Draw just the reflection on a second graphics buffer 
                Using gReflection As Graphics = Graphics.FromImage(reflectedImage)
                    gReflection.DrawImage(img, New Rectangle(0, 0, reflectedImage.Width, reflectedImage.Height), 0, img.Height - reflectedImage.Height, reflectedImage.Width, reflectedImage.Height, _
                    GraphicsUnit.Pixel)
                End Using
                reflectedImage.RotateFlip(RotateFlipType.RotateNoneFlipY)
                Dim imageRectangle As New Rectangle(destinationRectangle.X, destinationRectangle.Y, destinationRectangle.Width, CInt((destinationRectangle.Height * reflectivity) / 255))

                ' Draw the image on the original graphics 
                _Graphics.DrawImage(reflectedImage, imageRectangle)

                ' Finish the reflection using a gradiend brush 
                Dim brush As New LinearGradientBrush(imageRectangle, Color.FromArgb(255 - reflectivity, bgColor), bgColor, 90, False)
                _Graphics.FillRectangle(brush, imageRectangle)
            End Using

            Return newImage
        End Function



        '------------------------------

#Region "获取缩略图"
        ''' <summary> 
        ''' 获取正方形的缩略图 
        ''' </summary> 
        ''' <param name="img"></param> 
        ''' <param name="width"></param> 
        ''' <returns></returns> 
        Public Function GetThumbnailImage(ByVal img As Image, ByVal width As Integer) As Image
            If img Is Nothing OrElse width < 1 Then
                Return Nothing
            End If
            Dim _SrcRectangle As Rectangle
            Dim _X As Integer, _Y As Integer, _Width As Integer

            If img.Width > img.Height Then
                _X = CInt((img.Width - img.Height) / 2)
                _Y = 0
                _Width = img.Height
            Else
                _X = 0
                _Y = CInt((img.Height - img.Width) / 2)
                _Width = img.Width
            End If
            _SrcRectangle = New Rectangle(_X, _Y, _Width, _Width)

            Return Me.GetThumbnailImage(img, width, width, _SrcRectangle)
        End Function

        ''' <summary> 
        ''' 获取缩略图(保持图片比例) 
        ''' </summary> 
        ''' <param name="img"></param> 
        ''' <param name="width"></param> 
        ''' <param name="height"></param> 
        ''' <returns></returns> 
        Public Function GetThumbnailImage(ByVal img As Image, ByVal width As Integer, ByVal height As Integer) As Image
            Return Me.GetThumbnailImage(img, width, height, True)
        End Function

        ''' <summary> 
        ''' 缩略图 
        ''' </summary> 
        ''' <param name="img"></param> 
        ''' <param name="width"></param> 
        ''' <param name="height"></param> 
        ''' <param name="maintainRatio">是否保持图片比例</param> 
        ''' <returns></returns> 
        Public Function GetThumbnailImage(ByVal img As Image, ByVal width As Integer, ByVal height As Integer, ByVal maintainRatio As Boolean) As Image
            If img Is Nothing OrElse width < 1 OrElse height < 1 Then
                Return Nothing
            End If

            ' 保持比例 
            ' 
            If maintainRatio Then
                Dim _HeightRatio As Double = CDbl(img.Height) / img.Width
                Dim _WidthRatio As Double = CDbl(img.Width) / img.Height

                Dim _DesiredHeight As Integer = height
                Dim _DesiredWidth As Integer = width


                height = _DesiredHeight
                If _WidthRatio > 0 Then
                    width = Convert.ToInt32(height * _WidthRatio)
                End If

                If width > _DesiredWidth Then
                    width = _DesiredWidth
                    height = Convert.ToInt32(width * _HeightRatio)
                End If
            End If

            Dim _SrcRectangle As New Rectangle(0, 0, img.Width, img.Height)

            Return Me.GetThumbnailImage(img, width, height, _SrcRectangle)
        End Function

        Private Function GetThumbnailImage(ByVal img As Image, ByVal width As Integer, ByVal height As Integer, ByVal srcRectangle As Rectangle) As Image
            If img Is Nothing OrElse width < 1 OrElse height < 1 Then
                Return Nothing
            End If

            ' 新建一个bmp图片 
            ' 
            Dim _Bitmap As Image = New System.Drawing.Bitmap(width, height, PixelFormat.Format64bppArgb)

            ' 新建一个画板 
            ' 
            Using _Graphics As Graphics = System.Drawing.Graphics.FromImage(_Bitmap)

                ' 设置高质量插值法 
                ' 
                _Graphics.InterpolationMode = InterpolationMode.HighQualityBicubic

                ' 设置高质量,低速度呈现平滑程度 
                ' 
                _Graphics.SmoothingMode = SmoothingMode.HighQuality
                ' SmoothingMode.AntiAlias; 
                ' 高质量、低速度复合 
                ' 
                _Graphics.CompositingQuality = CompositingQuality.HighQuality

                _Graphics.PixelOffsetMode = PixelOffsetMode.HighQuality



                ' 清空画布并以透明背景色填充 
                ' 
                _Graphics.Clear(Color.Transparent)

                ' 在指定位置并且按指定大小绘制原图片的指定部分 
                ' 
                _Graphics.DrawImage(img, New Rectangle(0, 0, width, height), srcRectangle, GraphicsUnit.Pixel)

                Return _Bitmap
            End Using
        End Function

#End Region


#Region "WaterMark 水印"

        ''' <summary> 
        ''' 添加水印文字到图片中 
        ''' </summary> 
        ''' <param name="g"></param> 
        ''' <param name="width"></param> 
        ''' <param name="height"></param> 
        ''' <param name="watermarkText"></param> 
        ''' <param name="position"></param> 
        Public Sub AddWatermarkText(ByRef g As Graphics, ByVal width As Integer, ByVal height As Integer, ByVal watermarkText As String, ByVal position As WatermarkPosition)
            Dim alpha As Integer = 250
            Me.AddWatermarkText(g, width, height, watermarkText, position, alpha)
        End Sub

        ''' <summary> 
        ''' 添加水印文字到图片中 
        ''' </summary> 
        ''' <param name="g"></param> 
        ''' <param name="width"></param> 
        ''' <param name="height"></param> 
        ''' <param name="watermarkText"></param> 
        ''' <param name="position"></param> 
        ''' <param name="alpha"></param> 
        Public Sub AddWatermarkText(ByRef g As Graphics, ByVal width As Integer, ByVal height As Integer, ByVal watermarkText As String, ByVal position As WatermarkPosition, ByVal alpha As Integer)
            Dim _Sizes As Integer() = New Integer() {16, 14, 12, 10, 8, 6, _
            4}
            Dim _CrFont As Font = Nothing
            Dim _CrSize As New SizeF()
            For i As Integer = 0 To 6
                _CrFont = New Font("Verdana", _Sizes(i), FontStyle.Bold)
                _CrSize = g.MeasureString(watermarkText, _CrFont)

                If CUShort(_CrSize.Width) < CUShort(width) Then
                    Exit For
                End If
            Next

            Dim _Xpos As Single = 0
            Dim _Ypos As Single = 0

            Select Case position
                Case WatermarkPosition.TOP_LEFT
                    _Xpos = (CSng(width) * CSng(0.01)) + (_CrSize.Width / 2)
                    _Ypos = CSng(height) * CSng(0.01)
                    Exit Select
                Case WatermarkPosition.TOP_CENTER
                    _Xpos = (CSng(width) - _CrSize.Width) / 2
                    _Ypos = CSng(height) * CSng(0.01)
                    Exit Select
                Case WatermarkPosition.TOP_RIGHT
                    _Xpos = (CSng(width) * CSng(0.99)) - (_CrSize.Width / 2)
                    _Ypos = CSng(height) * CSng(0.01)
                    Exit Select
                Case WatermarkPosition.CENTER_LEFT
                    _Xpos = (CSng(width) * CSng(0.01)) + (_CrSize.Width / 2)
                    _Ypos = (CSng(height) - _CrSize.Height) / 2
                    Exit Select
                Case WatermarkPosition.CENTER_CENTER
                    _Xpos = (CSng(width) - _CrSize.Width) / 2
                    _Ypos = (CSng(height) - _CrSize.Height) / 2
                    Exit Select
                Case WatermarkPosition.CENTER_RIGHT
                    _Xpos = (CSng(width) * CSng(0.99)) - (_CrSize.Width / 2)
                    _Ypos = (CSng(height) - _CrSize.Height) / 2
                    Exit Select
                Case WatermarkPosition.BOTTOM_RIGHT
                    _Xpos = (CSng(width) - _CrSize.Width) / 2
                    _Ypos = (CSng(height) * CSng(0.99)) - _CrSize.Height
                    Exit Select
                Case WatermarkPosition.BOTTOM_CENTER
                    _Xpos = (CSng(width) * CSng(0.99)) - (_CrSize.Width / 2)
                    _Ypos = (CSng(height) * CSng(0.99)) - _CrSize.Height
                    Exit Select
                Case WatermarkPosition.BOTTOM_LEFT
                    _Xpos = (CSng(width) * CSng(0.01)) + (_CrSize.Width / 2)
                    _Ypos = (CSng(height) * CSng(0.99)) - _CrSize.Height
                    Exit Select
            End Select

            Dim _StrFormat As New StringFormat()
            _StrFormat.Alignment = StringAlignment.Center

            Dim _SemiTransBrush2 As New SolidBrush(Color.FromArgb(alpha, 0, 0, 0))
            g.DrawString(watermarkText, _CrFont, _SemiTransBrush2, _Xpos + 1, _Ypos + 1, _StrFormat)

            Dim _SemiTransBrush As New SolidBrush(Color.FromArgb(alpha, 255, 255, 255))
            g.DrawString(watermarkText, _CrFont, _SemiTransBrush, _Xpos, _Ypos, _StrFormat)


            _SemiTransBrush2.Dispose()
            _SemiTransBrush.Dispose()
        End Sub

        ''' <summary> 
        ''' 添加水印图片到图片中 
        ''' </summary> 
        ''' <param name="g"></param> 
        ''' <param name="width"></param> 
        ''' <param name="height"></param> 
        ''' <param name="watermark"></param> 
        ''' <param name="position"></param> 
        Public Sub AddWatermarkImage(ByRef g As Graphics, ByVal width As Integer, ByVal height As Integer, ByVal watermark As Image, ByVal position As WatermarkPosition)

            Using imageAttributes As New ImageAttributes()
                Dim _ColorMap As New ColorMap()

                _ColorMap.OldColor = Color.FromArgb(255, 0, 255, 0)
                _ColorMap.NewColor = Color.FromArgb(0, 0, 0, 0)
                Dim _RemapTable As ColorMap() = {_ColorMap}

                imageAttributes.SetRemapTable(_RemapTable, ColorAdjustType.Bitmap)

                Dim _ColorMatrixElements As Single()() = {New Single() {1.0F, 0.0F, 0.0F, 0.0F, 0.0F}, New Single() {0.0F, 1.0F, 0.0F, 0.0F, 0.0F}, New Single() {0.0F, 0.0F, 1.0F, 0.0F, 0.0F}, New Single() {0.0F, 0.0F, 0.0F, 1.0F, 0.0F}, New Single() {0.0F, 0.0F, 0.0F, 0.0F, 1.0F}}

                Dim _ColorMatrix As New ColorMatrix(_ColorMatrixElements)

                imageAttributes.SetColorMatrix(_ColorMatrix, ColorMatrixFlag.[Default], ColorAdjustType.Bitmap)

                Dim _Xpos As Integer = 0
                Dim _Ypos As Integer = 0

                Select Case position
                    Case WatermarkPosition.TOP_LEFT
                        _Xpos = 10
                        _Ypos = 10
                        Exit Select
                    Case WatermarkPosition.TOP_CENTER
                        _Xpos = CInt((width - watermark.Width) / 2)
                        _Ypos = 10
                        Exit Select
                    Case WatermarkPosition.TOP_RIGHT
                        _Xpos = ((width - watermark.Width) - 10)
                        _Ypos = 10
                        Exit Select
                    Case WatermarkPosition.CENTER_RIGHT
                        _Xpos = ((width - watermark.Width) - 10)
                        _Ypos = CInt((height - watermark.Height) / 2)
                        Exit Select
                    Case WatermarkPosition.CENTER_CENTER
                        _Xpos = CInt((width - watermark.Width) / 2)
                        _Ypos = CInt((height - watermark.Height) / 2)
                        Exit Select
                    Case WatermarkPosition.CENTER_LEFT
                        _Xpos = 10
                        _Ypos = CInt((height - watermark.Height) / 2)
                        Exit Select
                    Case WatermarkPosition.BOTTOM_RIGHT
                        _Xpos = ((width - watermark.Width) - 10)
                        _Ypos = height - watermark.Height - 10
                        Exit Select
                    Case WatermarkPosition.BOTTOM_CENTER
                        _Xpos = CInt((width - watermark.Width) / 2)
                        _Ypos = height - watermark.Height - 10
                        Exit Select
                    Case WatermarkPosition.BOTTOM_LEFT
                        _Xpos = 10
                        _Ypos = height - watermark.Height - 10
                        Exit Select
                End Select

                g.DrawImage(watermark, New Rectangle(_Xpos, _Ypos, watermark.Width, watermark.Height), 0, 0, watermark.Width, watermark.Height, _
                GraphicsUnit.Pixel, imageAttributes)


                watermark.Dispose()
                imageAttributes.Dispose()
            End Using
        End Sub

#End Region




#End Region



    End Class

End Namespace



